package top.csmcool.musicapi.resource;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import top.csmcool.musicapi.client.NavidromeClient;
import top.csmcool.musicapi.config.SystemProperties;
import top.csmcool.musicapi.domain.UserPlatformBindInfo;
import top.csmcool.musicapi.domain.Users;
import top.csmcool.musicapi.enums.PlatformEnum;
import top.csmcool.musicapi.model.api.navidrome.*;
import top.csmcool.musicapi.model.api.navidrome.SongInfo;
import top.csmcool.musicapi.model.playlist.*;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/*
 * @description navidrome自建库音乐资源
 * @date 2025/1/29
 * @author shijin
 * @version 1.0
 */
@Component("navidrome")
@RequiredArgsConstructor
public class NavidromeResource implements MusicResource{

    private final SystemProperties systemProperties;
    private final NavidromeClient navidromeClient;

    @Override
    public List<PlayListMusicInfo> getTracks(TracksRequest requestRequest, Users users, UserPlatformBindInfo one) {
        List<PlayListMusicInfo> list = new LinkedList<>();
        // 获取token
        one = getUserPlatformBindInfo(users, one, systemProperties.getRegisterUrl());
        String username = one.getUsername();
        String password = one.getPassword();
        String platformUrl = one.getPlatformUrl();
        NavidromeLoginResult tokenInfo = navidromeClient.getTokenInfo(platformUrl,username, password);

        List<MusicTrack> musicTrack = navidromeClient.getMusicTracks(tokenInfo,
                platformUrl,
                requestRequest.getId(), requestRequest.getStart(), requestRequest.getEnd());
        // 获取列表
        buildResult(musicTrack, tokenInfo, platformUrl, list);

        return list;
    }

    @Override
    public List<LyricInfo> getLyric(LyricRequest body, Users users, UserPlatformBindInfo one) {
        List<LyricInfo> list = new LinkedList<>();
        // 获取token
        one = getUserPlatformBindInfo(users, one, systemProperties.getRegisterUrl());
        String username = one.getUsername();
        String password = one.getPassword();
        String platformUrl = one.getPlatformUrl();
        NavidromeLoginResult tokenInfo = navidromeClient.getTokenInfo(platformUrl,username, password);

        SongInfo songInfo = navidromeClient.getSongInfo(tokenInfo, platformUrl, body.getId());

        String lyrics = songInfo.getLyrics();
        if(lyrics == null || lyrics.isEmpty()) {
            return list;
        }
        JSONArray objects = JSONUtil.parseArray(lyrics);
        List<Lyrics> list1 = JSONUtil.toList(objects, Lyrics.class);
        if(list1.isEmpty()) {
            return list;
        }
        List<LyricLine> line = list1.get(0).getLine();
        for (LyricLine lyricLine : line) {
            LyricInfo lyricInfo = new LyricInfo();

            lyricInfo.setText(lyricLine.getValue());
            lyricInfo.setTime(lyricLine.getStart());

            list.add(lyricInfo);
        }

        return list;
    }

    @Override
    public List<SongCollection> getPlayList(PlayListRequest body, Users users, UserPlatformBindInfo one) {
        // 获取token
        one = getUserPlatformBindInfo(users, one, systemProperties.getRegisterUrl());
        String username = one.getUsername();
        String password = one.getPassword();
        String platformUrl = one.getPlatformUrl();
        NavidromeLoginResult tokenInfo = navidromeClient.getTokenInfo(platformUrl,username, password);

        List<SongCollection> playLists = navidromeClient.getPlayLists(tokenInfo,
                platformUrl,
                body.getStart(),
                body.getEnd());

        for (SongCollection playList : playLists) {
            // 屎山代码
            buildAlbumInfo(playList, tokenInfo, platformUrl);
        }

        return playLists;
    }

    @Override
    public List<SongCollection> getPublicPlayList(PlayListRequest body, Users users, UserPlatformBindInfo one) {
        // 获取token
        one = getUserPlatformBindInfo(users, one, systemProperties.getRegisterUrl());
        String username = one.getUsername();
        String password = one.getPassword();
        String platformUrl = one.getPlatformUrl();
        NavidromeLoginResult tokenInfo = navidromeClient.getTokenInfo(platformUrl,username, password);

        List<SongCollection> playLists = navidromeClient.getPublicPlayLists(tokenInfo,
                platformUrl,
                body.getStart(),
                body.getEnd());

        for (SongCollection playList : playLists) {
            if(playList.getSongCount() == 0) {
                continue;
            }
            buildAlbumInfo(playList, tokenInfo, platformUrl);
        }

        return playLists;
    }

    @Override
    public List<PlayListMusicInfo> search(SearchRequest body, Users users, UserPlatformBindInfo one) {
        List<PlayListMusicInfo> list = new LinkedList<>();
        // 获取token
        one = getUserPlatformBindInfo(users, one, systemProperties.getRegisterUrl());
        String username = one.getUsername();
        String password = one.getPassword();
        String platformUrl = one.getPlatformUrl();
        NavidromeLoginResult tokenInfo = navidromeClient.getTokenInfo(platformUrl,username, password);

        List<MusicTrack> musicTrack = navidromeClient.search(tokenInfo,
                platformUrl,
                body.getName(),
                body.getStart(),
                body.getEnd());
        // 获取列表
        buildResult(musicTrack, tokenInfo, platformUrl, list);

        return list;
    }

    @Override
    public top.csmcool.musicapi.model.playlist.SongInfo getSongUrl(SongUrlRequest body, Users users, UserPlatformBindInfo one) {
        top.csmcool.musicapi.model.playlist.SongInfo songInfo = new top.csmcool.musicapi.model.playlist.SongInfo();
        // 获取token
        one = getUserPlatformBindInfo(users, one, systemProperties.getRegisterUrl());
        String username = one.getUsername();
        String password = one.getPassword();
        String platformUrl = one.getPlatformUrl();
        NavidromeLoginResult tokenInfo = navidromeClient.getTokenInfo(platformUrl,username, password);
        Map<String, String> urlMap = new HashMap<>();
        urlMap.put("id", body.getId());
        String url = buildImageUrl("/rest/stream?", urlMap, tokenInfo);
        songInfo.setSongUrl(platformUrl + url);
        return songInfo;
    }

    /**
     * 补充专辑缺少信息 封面图片
     * @param playList
     * @param tokenInfo
     * @param platformUrl
     */
    private void buildAlbumInfo(SongCollection playList, NavidromeLoginResult tokenInfo, String platformUrl) {
        List<MusicTrack> musicTrack = navidromeClient.getMusicTracks(tokenInfo,
                platformUrl,
                playList.getId(), 0, 1);
        Map<String, String> map = new HashMap<>();
        if(!musicTrack.isEmpty()) {
            map.put("id", "mf-" + musicTrack.get(0).getMediaFileId());
        }
        String image = buildImageUrl("/rest/getCoverArt?", map, tokenInfo);
        playList.setCoverImgUrl(platformUrl + image);
    }

    private static void buildResult(List<MusicTrack> musicTrack, NavidromeLoginResult tokenInfo, String platformUrl, List<PlayListMusicInfo> list) {
        for (MusicTrack track : musicTrack) {
            PlayListMusicInfo playListMusicInfo = new PlayListMusicInfo();
            playListMusicInfo.setName(track.getOrderTitle());
            String mediaFileId = track.getMediaFileId();
            if(mediaFileId == null) {
                mediaFileId = track.getId();
            }
            playListMusicInfo.setId(mediaFileId);
            playListMusicInfo.setSinger(track.getOrderArtistName());
            playListMusicInfo.setAlbum(track.getOrderAlbumName());
            double duration = track.getDuration();
            playListMusicInfo.setDuration(Double.valueOf(duration).longValue());
            Map<String, String> map = new HashMap<>();
            map.put("id", "mf-" + mediaFileId);
            String image = buildImageUrl("/rest/getCoverArt?",map, tokenInfo);
            playListMusicInfo.setImage(platformUrl + image);
            Map<String, String> urlMap = new HashMap<>();
            urlMap.put("id", mediaFileId);
            String url = buildImageUrl("/rest/stream?", urlMap, tokenInfo);
            playListMusicInfo.setUrl(platformUrl + url);
            playListMusicInfo.setPlatform(PlatformEnum.NAVIDROME.getCode());
            playListMusicInfo.setPlatformName(PlatformEnum.NAVIDROME.getName());

            list.add(playListMusicInfo);
        }
    }

    public static String buildImageUrl(String baseUrl, Map<String, String> params,
                                       NavidromeLoginResult tokenInfo){
        // Add the mandatory parameters
        params.put("t", tokenInfo.getSubsonicToken());
        params.put("s", tokenInfo.getSubsonicSalt());
        params.put("f", "json");
        params.put("u", tokenInfo.getUsername());
        params.put("v", "1.8.0");
        params.put("c", "NavidromeUI");
        params.put("_", String.valueOf(System.currentTimeMillis()));
        params.put("size", "300");

        // Build the query string dynamically
        StringBuilder queryString = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (entry.getValue() != null && !entry.getValue().isEmpty()) {
                if (!queryString.isEmpty()) {
                    queryString.append("&");
                }
                queryString.append(entry.getKey()).append("=").append(entry.getValue());
            }
        }

        return baseUrl + queryString.toString();
    }

    @Override
    public JSONObject requestResource(JSONObject jsonObject, Users users, UserPlatformBindInfo one) {
        List<PlayListMusicInfo> list = new LinkedList<>();
        // 获取token
        one = getUserPlatformBindInfo(users, one, systemProperties.getRegisterUrl());
        String username = one.getUsername();
        String password = one.getPassword();
        String platformUrl = one.getPlatformUrl();
        NavidromeLoginResult tokenInfo = navidromeClient.getTokenInfo(platformUrl,username, password);
        return navidromeClient.requestResource(tokenInfo,
                platformUrl, jsonObject);
    }
}
